﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using ShareCode.Entity;
using ShareCode.Entity.Corpus;

namespace ClientAppraise.ViewModels;

public abstract partial class BaseBaseTreeDataGridM : ObservableValidator
{
    public long Id
    {
        get; set;
    }

    public Action<bool?>? FunCheck;

    [ObservableProperty]
    private bool? isChecked = false;

    [ObservableProperty]
    private Visibility showCheckBox;
    partial void OnIsCheckedChanged(bool? value)
    {
        MyOnIsCheckedChanged(value);
    }

    private bool toggleIsChecked;
    public bool ToggleIsChecked
    {
        get => toggleIsChecked;
        set
        {
            toggleIsChecked = value;
            SetProperty(ref toggleIsChecked, value);

            if (toggleIsChecked)
            {
                AddNode();
            }
            else
            {
                RemoveNode();
            }

        }
    }
    /// <summary>
    /// 左侧缩进
    /// </summary>
    public double ToggleMarginLeft
    {
        get; set;
    }
    public int Level
    {
        get; set;
    }

    public string? ToggleTitle
    {
        get; set;
    }

    public Visibility ToggleIsVisible => HasSon ? Visibility.Visible : Visibility.Collapsed;

    public virtual bool HasSon => false;

    public abstract void AddNode();
    public abstract void RemoveNode();

    public abstract void MyOnIsCheckedChanged(bool? value);

}

public class BaseTreeDataGridM<T> : BaseBaseTreeDataGridM where T : BaseTreeEntity
{

    public ObservableCollection<BaseTreeDataGridM<T>>? DataSource { get; set; }

    public BaseTreeDataGridM<T>? Parent { get; set; }

    public override void MyOnIsCheckedChanged(bool? value)
    {
        if (value == null) return;

        foreach (var item in Subordinates)
        {
            item.IsChecked = value;
        }

        if (Parent == null) return;

        int? CheckCount = 0;
        foreach (var item in Parent.Subordinates)
        {
            if (!item.IsChecked.HasValue)
            {
                CheckCount = null;
                break;
            }

            if (item.IsChecked.Value)
            {
                CheckCount++;
            }
        }

        if (!CheckCount.HasValue)
        {
            Parent.IsChecked = null;
        }
        else if (CheckCount.Value == Parent.Subordinates.Count)
        {
            Parent.IsChecked = true;
        }
        else if (CheckCount.Value == 0)
        {
            Parent.IsChecked = false;
        }
        else
        {
            Parent.IsChecked = null;
        }
    }

    public override bool HasSon => !(Subordinates == default || Subordinates.Count < 1);

    public List<BaseTreeDataGridM<T>> Subordinates = [];
    static double MarginLeft
    {
        get; set;
    } = 20;

    public void SetParam(int pMarginLeft)
    {
        MarginLeft = pMarginLeft;
    }

    public T? Entity
    {
        get; set;
    }

    public override void AddNode()
    {

        if (DataSource == default || DataSource.Count < 1)
        {
            return;
        }

        var index = DataSource.ToList().FindIndex(t => t.Id == Id);

        foreach (var a in Subordinates)
        {
            a.ToggleMarginLeft = MarginLeft * a.Level;
            a.IsChecked = this.IsChecked;

            if (index + 1 <= DataSource.Count)
            {
                DataSource.Insert(++index, (BaseTreeDataGridM<T>)a);
            }
            else
            {
                DataSource.Append(a);
            }
        }
    }

    public override void RemoveNode()
    {
        if (DataSource == default || DataSource.Count < 1) return;

        var tempMoale = this;

        if (tempMoale.Subordinates == default) return;

        foreach (var a in tempMoale.Subordinates)
        {
            a.ToggleIsChecked = false;

            var item = DataSource.FirstOrDefault(t => t.Id == a.Id);

            if (item != default)
            {
                DataSource.Remove(item);
            }
        }

    }

    public static List<BaseTreeDataGridM<T>> GetItems(ObservableCollection<BaseTreeDataGridM<T>> Data, ICollection<long> ids)
    {
        List<BaseTreeDataGridM<T>> re = [];

        void fun(ICollection<BaseTreeDataGridM<T>> sonData)
        {
            foreach (var a in sonData)
            {
                if (ids.Contains(a.Entity!.Id))
                {
                    re.Add(a);
                }
            }
        }

        fun(Data);
        return re;
    }


    public static ObservableCollection<BaseTreeDataGridM<T>> ExpandAll(ObservableCollection<BaseTreeDataGridM<T>> Data)
    {
        void fun(ICollection<BaseTreeDataGridM<T>> sonData)
        {
            foreach (var a in sonData)
            {
                if (a.HasSon)
                {
                    a.ToggleIsChecked = true;
                    fun(a.Subordinates);
                }
            }
        }
        //因为列表其实是都放到了最外层，所以最外层集合是会产生变化的，所以这里先把有子级的给选出来，这样就集合就不会产生变化了
        var tempData = Data.Where(t => t.HasSon).ToList();
        fun(tempData);
        return Data;
    }
    public static ObservableCollection<BaseTreeDataGridM<T>> ExpandItem(ObservableCollection<BaseTreeDataGridM<T>> Data, ICollection<long> ids)
    {

        void fun(ICollection<BaseTreeDataGridM<T>> sonData)
        {
            foreach (var a in sonData)
            {
                if (a.HasSon)
                {
                    if (ids.Contains(a.Entity!.Id))
                    {
                        a.ToggleIsChecked = true;
                    }

                    fun(a.Subordinates);
                }
            }
        }
        //因为列表其实是都放到了最外层，所以最外层集合是会产生变化的，所以这里先把有子级的给选出来，这样就集合就不会产生变化了
        var tempData = Data.Where(t => t.HasSon).ToList();
        fun(tempData);
        return Data;
    }


    public static ObservableCollection<BaseTreeDataGridM<T>> SelectItem(ObservableCollection<BaseTreeDataGridM<T>> Data, ICollection<long> ids)
    {
        //单选时如何搞呢！！！


        return Data;
    }
    public static ObservableCollection<BaseTreeDataGridM<T>> CheckCheckBoxItem(ObservableCollection<BaseTreeDataGridM<T>> Data, ICollection<long> ids)
    {
        void fun(ICollection<BaseTreeDataGridM<T>> sonData)
        {
            foreach (var a in sonData)
            {
                if (ids.Contains(a.Entity!.Id))
                {
                    a.IsChecked = true;
                }

                if (a.HasSon)
                {
                    fun(a.Subordinates);
                }
            }
        }

        fun(Data);

        return Data;
    }


    public static ObservableCollection<BaseTreeDataGridM<T>> GetList(List<T> values, Func<T, string>? getToggleTitle = null, Action<bool?>? funCheck = null)
    {
        ObservableCollection<BaseTreeDataGridM<T>> DataSource = [];

        if (values == default || values.Count < 1)
        {
            return DataSource;
        }

        //OldDataSource = values;

        var lists = GetTreeList(values, DataSource, getToggleTitle, 0, 0, funCheck);

        if (lists != default)
        {
            foreach (var a in lists)
            {
                DataSource.Add(a);
            }
        }

        return DataSource;
    }
    private static List<BaseTreeDataGridM<T>>? GetTreeList(List<T> values, ObservableCollection<BaseTreeDataGridM<T>> DataSource, Func<T, string>? getToggleTitle = null, long parentid = 0, int level = 0, Action<bool?>? funCheck = null)
    {
        List<BaseTreeDataGridM<T>> list = [];
        var templist = values.Where(t => t.TreeParentId == parentid);

        if (templist == default || !templist.Any())
        {
            return null;
        }

        foreach (var a in templist)
        {
            var temp = new BaseTreeDataGridM<T>
            {
                Entity = a,
                Level = level,
                Id = a.Id,
                ToggleTitle = getToggleTitle == null ? a.Title : getToggleTitle(a),
                FunCheck = funCheck,
                ShowCheckBox = funCheck == null ? Visibility.Collapsed : Visibility.Visible,
                DataSource = DataSource
            };

            var sons = GetTreeList(values, DataSource, getToggleTitle, temp.Id, level + 1, funCheck);

            if (sons != null)
            {
                temp.Subordinates = sons;

                foreach (var item in temp.Subordinates)
                {
                    item.Parent = temp;
                }
            }
            list.Add(temp);
        }

        return list;
    }


}
